package com.lagou.niancheng.lagouservicegateway;

import com.lagou.niancheng.lagou.service.common.LagouConstants;
import com.lagou.niancheng.lagou.service.common.Result;
import com.lagou.niancheng.lagou.service.common.UserApi;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;


@Component
public class AccessTokenFilter implements GatewayFilter, ApplicationContextAware {

    private static final Logger logger = LoggerFactory.getLogger(AccessTokenFilter.class);
    @Reference(check = false)
    private UserApi userApi;

    private ApplicationContext applicationContext;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        MultiValueMap<String, HttpCookie> cookies = request.getCookies();
        List<HttpCookie> httpCookies = cookies.get(LagouConstants.ACCESS_TOKEN_COOKIE_NAME);
        // 如果cookie为空，则直接报错
        if (CollectionUtils.isEmpty(httpCookies)) {
            return noLogin(response);
        }

        String token = httpCookies.get(0).getValue();

        if (userApi == null) {
            userApi = applicationContext.getBean(UserApi.class);
        }
        Result<Boolean> booleanResult = userApi.checkToken(token);
        booleanResult.check();
        // 如果token正确，则成功
        if (booleanResult.isSuccess() && booleanResult.getData()) {
            return chain.filter(exchange);
        } else {
            // 否则报错
            return noLogin(response);
        }
    }

    private Mono<Void> noLogin(ServerHttpResponse response) {
        //设置status
        logger.info("TokenFilter拦截非法请求，没有检测到token............");
        response.setStatusCode(HttpStatus.FORBIDDEN);
        byte[] bytes = "403 forbidden".getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        return response.writeWith(Flux.just(buffer));
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
